package com.example.usercenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.example.usercenter.Exception.BusinsessException;
import com.example.usercenter.common.ErrorCode;
import com.example.usercenter.constant.TeamStatus;
import com.example.usercenter.mapper.TeamMapper;
import com.example.usercenter.model.domain.Team;
import com.example.usercenter.model.domain.User;
import com.example.usercenter.model.domain.UserTeam;
import com.example.usercenter.model.dto.TeamJoinQuery;
import com.example.usercenter.model.dto.TeamQuery;
import com.example.usercenter.model.dto.TeamUpdateQuery;
import com.example.usercenter.model.request.TeamQueryRequest;
import com.example.usercenter.model.vo.UserVo;
import com.example.usercenter.service.TeamService;
import com.example.usercenter.service.UserService;
import com.example.usercenter.service.UserTeamService;
import com.example.usercenter.utils.AlgorithmDistance;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.util.*;
import java.util.stream.Collectors;

import static com.example.usercenter.constant.UserConstant.USERLOGINSTATUS;

/**
* @author asus
* @description 针对表【team(队伍表)】的数据库操作Service实现
* @createDate 2025-01-18 10:59:47
*/
@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
    implements TeamService {

    @Resource
    private UserService userService;
    @Resource
    private UserTeamService userTeamService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createTeam(Team team, HttpServletRequest request) {
        if (team == null){
            throw new BusinsessException(ErrorCode.PARAMS_ERROR);
        }
        //获取登录用户，判断用户是否登录
        User loginUser = getLoginUser(request);
        if (loginUser == null){
            throw new BusinsessException(ErrorCode.NOT_LOGIN);
        }
        //创建的最大人数是否符合
        Integer maxNum = team.getMaxNum();
        if (maxNum < 1 || maxNum > 20){
            throw new BusinsessException(ErrorCode.PARAMS_ERROR);
        }
        if (StringUtils.isNotBlank(team.getDescription()) && team.getDescription().length() >512 ){
            throw new BusinsessException(ErrorCode.PARAMS_ERROR);
        }
        //判断队伍状态
        Integer status = team.getStatus();
        TeamStatus element = TeamStatus.getElementByValue(status);
        if (element == null){
            throw new BusinsessException(ErrorCode.PARAMS_ERROR,"状态码为空");
        }
        //如果创建的队伍是加密队伍，则需要判断是否输入密码且密码是否符合规范
        if (element.equals(TeamStatus.SECRET)){
            if (team.getPassword() == null || team.getPassword().length() > 32){
                throw new BusinsessException(ErrorCode.PARAMS_ERROR,"密码设置不正确");
            }
        }
        //判断该用户创建的队伍是否超过上限
        QueryWrapper query = new QueryWrapper();
        query.eq("userId", loginUser.getId());
        int count = this.count(query);
        if (count >= 5){
            throw new BusinsessException(ErrorCode.PARAMS_ERROR,"队伍创建过多");
        }
        team.setId(null);
        team.setUserId(loginUser.getId());
        boolean result = this.save(team);
        if (!result){
            throw new BusinsessException(ErrorCode.SYSTEM_ERROR,"插入失败");
        }
        //插入用户——队伍关系表
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(loginUser.getId());
        userTeam.setTeamId(team.getId());
        userTeam.setJoinTime(new Date());
        return userTeamService.save(userTeam);
    }

    @Override
    public List<UserVo> listTeams(TeamQuery teamQuery,Boolean isAdmin) {
        QueryWrapper query = new QueryWrapper();
        if (teamQuery != null){
            Long id = teamQuery.getId();
            if (id != null){
                query.eq("id",id);
            }
            //关键词搜索
            String searchText = teamQuery.getSearchText();
            if (StringUtils.isNotBlank(searchText)){

            }
            //过期日期
            Date expireTime = teamQuery.getExpireTime();
            //te
            //query.lt("expireTime",expireTime);
            String name = teamQuery.getName();
            if (name != null){
                query.like("name",teamQuery.getName());
            }
            String description = teamQuery.getDescription();
            if (description != null){
                query.like("description",description);
            }
            Integer maxNum = teamQuery.getMaxNum();
            if (maxNum != null && maxNum>0){
                query.eq("maxNum",maxNum);
            }
            Integer status = teamQuery.getStatus();
            TeamStatus statusEnum = TeamStatus.getElementByValue(status);
            if (status == null){
                 statusEnum = TeamStatus.PUBLIC;
            }
            if (!isAdmin && !statusEnum.equals(TeamStatus.PUBLIC)){
                throw new BusinsessException(ErrorCode.NOT_AUTHOR,"没有查询权限");
            }
            query.eq("status",statusEnum.getValue());
            List<UserVo> userVoList = new ArrayList<>();
            List<Team> list = this.list(query);
            if (CollectionUtils.isEmpty(list)){
                return new ArrayList<>();
            }
            for (Team team1 : list) {
                Integer userId = team1.getUserId();
                if (userId == null){
                    continue;
                }
                User user = userService.getById(userId);
                User saftUser = userService.saftUser(user);
                UserVo userVo = new UserVo();
                BeanUtils.copyProperties(saftUser,userVo);
                userVoList.add(userVo);
            }
            return userVoList;
        }
        List<UserVo> list = this.list(query);
        return list;
    }


    @Override
    public boolean updateTeam(TeamUpdateQuery teamUpdateQuery, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        Long id = teamUpdateQuery.getId();
        Team t = this.getById(id);
        if (t == null){
            throw new BusinsessException(ErrorCode.NULL_ERROR,"查询队伍不存在");
        }
        if (t.getUserId() != loginUser.getId() && userService.isAdmin(request)){
            throw new BusinsessException(ErrorCode.NOT_AUTHOR,"没有修改权限");
        }
        Integer status = teamUpdateQuery.getStatus();
        TeamStatus statusEnum = TeamStatus.getElementByValue(status);
        if (statusEnum.equals(TeamStatus.SECRET)){
            String password = teamUpdateQuery.getPassword();
            if (password == null){
                throw new BusinsessException(ErrorCode.NULL_ERROR,"请传入密码");
            }
        }
        Team updateTeam = new Team();
        BeanUtils.copyProperties(teamUpdateQuery,updateTeam);

        return this.updateById(updateTeam);
    }

    @Override
    public Boolean joinTeam(TeamJoinQuery teamJoinQuery,HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        QueryWrapper queryWrapper = new QueryWrapper();
        if (teamJoinQuery == null){
            throw new BusinsessException(ErrorCode.NULL_ERROR);
        }
        Integer id = loginUser.getId();
        queryWrapper.eq("userId",id);
        int count = this.count(queryWrapper);
        if (count >= 5 ){
            throw new BusinsessException(ErrorCode.PARAMS_ERROR,"加入队伍上限");
        }
        Long joinId = teamJoinQuery.getId();
        if (joinId == null){
            throw new BusinsessException(ErrorCode.PARAMS_ERROR,"加入队伍不存在");
        }
        Team team = this.getById(joinId);
        Date expireTime = team.getExpireTime();
        if (expireTime == null && expireTime.before(new Date())){
            throw new BusinsessException(ErrorCode.PARAMS_ERROR,"队伍过期");
        }

        Integer status = team.getStatus();
        TeamStatus teamStatus = TeamStatus.getElementByValue(status);
        //禁止加入私有队伍
        if (TeamStatus.RIVATE.equals(teamStatus)){
            throw new BusinsessException(ErrorCode.PARAMS_ERROR,"禁止加入私有队伍");
        }
        //队友加密队伍，需要校验队伍密码
        if (teamStatus.equals(TeamStatus.SECRET)){
            String password = team.getPassword();
            if (password== null || !password.equals(teamJoinQuery.getPassword())){
                throw new BusinsessException(ErrorCode.PARAMS_ERROR,"传入的密码有误");
            }
        }
        Integer maxNum = team.getMaxNum();
        QueryWrapper joinQuery =new QueryWrapper();
        joinQuery.eq("id",joinQuery);
        int hasCount = userTeamService.count(joinQuery);
        if (hasCount >= maxNum){
            throw new BusinsessException(ErrorCode.PARAMS_ERROR,"加入队伍人数已满");
        }
        //不能加入已经加入的队伍
        QueryWrapper joinTeamQuery = new QueryWrapper();
        joinTeamQuery.eq("userId",loginUser.getId());
        joinTeamQuery.eq("teamId",joinId);
        int userCount = userTeamService.count(joinTeamQuery);
        if (userCount > 0){
            throw new BusinsessException(ErrorCode.PARAMS_ERROR,"已经加入该队伍");
        }
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(loginUser.getId());
        userTeam.setTeamId(joinId);
        userTeam.setJoinTime(new Date());
        return userTeamService.save(userTeam);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean exitTeam(TeamQueryRequest teamQueryRequest, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (teamQueryRequest == null){
            throw new BusinsessException(ErrorCode.NULL_ERROR);
        }
        //判断队伍是否存在
        Long id = teamQueryRequest.getId();
        Team team = this.getById(id);
        if (team == null){
            throw new BusinsessException(ErrorCode.NULL_ERROR,"未查询到该队伍");
        }
        //查询队伍中的成员数量
        QueryWrapper query = new QueryWrapper();
        query.eq("teamId",id);
        int userCount = userTeamService.count(query);
        if (userCount == 1){
            //如果只有一个人，移除关联关系和队伍信息
            this.removeById(id);
            QueryWrapper userTeamQuery = new QueryWrapper();
            userTeamQuery.eq("teamId",id);
            return userTeamService.remove(userTeamQuery);
        }else {
            //select joinTime from team_user order by joinTime desc
            //超过一个人则判断当前用户是否为创建者
            Integer creater = team.getUserId();
            if (creater == loginUser.getId()){
                //权限转移
                //1.查询到已加入队伍的用户信息和加入时间
                QueryWrapper userTeamQuery = new QueryWrapper();
                userTeamQuery.eq("teamId",id);
                userTeamQuery.last("order by id asc limit 2");
                List<UserTeam> list = userTeamService.list(userTeamQuery);
                if (CollectionUtils.isEmpty(list) || list.size() < 1){
                    throw new BusinsessException(ErrorCode.SYSTEM_ERROR);
                }
                //2.移除队伍信息和关联关系
                UserTeam userTeam = list.get(1);
                Integer nextLeaderId = userTeam.getUserId();
                Team team1 = new Team();
                team1.setUserId(nextLeaderId);
                team1.setId(id);
                Boolean result = this.updateById(team1);
                if (!result){
                    throw new BusinsessException(ErrorCode.SYSTEM_ERROR,"更新异常");
                }
                userTeamQuery = new QueryWrapper();
                userTeamQuery.eq("teamId",id);
                userTeamQuery.eq("userId",list.get(0).getUserId());
                return userTeamService.remove(userTeamQuery);

            }else {
                //退出退伍
                QueryWrapper removeQuery = new QueryWrapper();
                removeQuery.eq("teamId",id);
                removeQuery.eq("userId",loginUser.getId());
                return userTeamService.remove(removeQuery);
            }
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean dismissTeam(TeamQueryRequest teamQueryRequest,HttpServletRequest request) {
        if (teamQueryRequest == null){
            throw new BusinsessException(ErrorCode.NULL_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        Long teamId = teamQueryRequest.getId();
        Team team = this.getById(teamId);
        if (team == null){
            throw new BusinsessException(ErrorCode.SYSTEM_ERROR,"队伍不存在");
        }
        Integer userLeaderId = team.getUserId();
        //校验你是不是队伍的队长
        if (userLeaderId == loginUser.getId()){
            QueryWrapper queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("teamId",teamId);
            userTeamService.remove(queryWrapper);
            return this.removeById(teamId);
        }else {
            throw new BusinsessException(ErrorCode.NOT_AUTHOR,"没有解散队伍的权限");
        }
    }

    @Override
    public List<UserVo> matchTags(long num, User loginUser) {
        if (num <= 0){
            throw new BusinsessException(ErrorCode.PARAMS_ERROR);
        }
        String tags = loginUser.getTags();
        Gson gson = new Gson();
        List<String> tag = gson.fromJson(tags, new TypeToken<List<String>>() {}.getType());
        TreeMap<Integer, Integer> treeMap = new TreeMap<>();
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("id,tags");
        queryWrapper.isNotNull("tags");
        List<User> userlist = userService.list(queryWrapper);
        int i=0;
        for (User user : userlist) {
            String userTags = user.getTags();
            if (userTags == null || user.getId() == loginUser.getId()){
                continue;
            }
            List<String> userTag = gson.fromJson(userTags, new TypeToken<List<String>>() {}.getType());
            int distance = AlgorithmDistance.minEditDistance(tag, userTag);
            treeMap.put(i,distance);
            i++;
        }
        List<Map.Entry<Integer, Integer>> top5Entries = treeMap.entrySet().stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) // 按值降序排序
                .limit(5) // 获取前5个条目
                .collect(Collectors.toList()); // 收集成 List

        List<UserVo> userVoList = new ArrayList<>();

        for (int j = 0; j < top5Entries.size(); j++) {
            Map.Entry<Integer, Integer> entry = top5Entries.get(j);
            User user = userlist.get(entry.getKey());
            UserVo userVo = new UserVo();
            BeanUtils.copyProperties(user,userVo);
            userVoList.add(userVo);
        }
        return userVoList;
    }

    public User getLoginUser(HttpServletRequest request){
        Object o = request.getSession().getAttribute(USERLOGINSTATUS);
        return (User) o;
    }
}




